Library Bloat
The average size of a web page has been steadily increasing since the beginning of the internet. Over the last few years, with the creation of package registries and package managers like NPM, Yarn, and Bower, the size of our pages has grown at an unprecedented rate. These technologies allow for incredibly fast iteration and deployment of new features and give you the vast array of outsourced tools that you can make use of on your web application. But they come at a cost.
The cost of easy development
So what is the cost of using others’ work? Well, it depends on what you’re doing. I took a look at the size cost of an empty Create React App shell. While using the built-in Lighthouse feature of Chrome Developer Tools an empty Create React App shell costs 602.3 KiB on a production build and ~1.2 MiB on a development build. That is a lot of JavaScript to display a rotating GIF and a Hello World page. For perspective 1 MiB is a 500-page book’s worth of text. Create React App is likely the most common starter for React projects and over half a MiB for a production build is quite expensive.
Let’s say we needed to add things on top of our Create React App shell. Perhaps a client-side router? A solution to routing in React is React Router. React Router is a wonderful library. It works well. It has multiple variations on types of routers that can solve the routing problem in many different ways. How much would React Router add to your project? According to the latest build on NPM 672 KiB. You just doubled the JavaScript size of your project by installing a router. I don’t know every feature that React Router has, but that is a lot. I did build my own hash router. It only took me a few hours to write. The hash router’s size is only 6.28 KiB at the time I wrote this blog. This site uses that hash router. It seems to solve my problem just fine. I’m sure that React Router is probably an infinitely better solution that solves the problem for 1000 different use cases. If you are like me you probably didn’t need to solve 1000 use cases. You just wanted to route your user to specific content in your application. The cost of solving everyone’s problem with one tool comes at a cost in size.
Let’s take another look at a library that has been popular with the rise of GraphQL. Apollo Client and the React Apollo integration are common libraries used in React-based GraphQL projects. Apollo Client is 3.64 MiB on NPM. The React Apollo integration is 12.5 KiB on NPM. That is crazy large for a library used to send POST requests to a server. You can do that with a 10 line fetch command! To put things into perspective the original Doom is 2.39 MiB of space. The Apollo Client library for retrieving information asynchronously is 1.5 times the size of the original Doom! I’d much rather download Doom than Apollo Client. You might say “Apollo Client has some advanced caching.” You are right. It has a lot of features and most of them I don’t use (and you probably don’t either). I think most of the time I don’t need a caching layer. I find myself fighting against caching with Apollo Client twice as often as it helps me solve my problem. It probably slows me down more than it helps.
The list goes on in regards to the JavaScript tools we use and the crazy high size cost it takes to use them.
Who cares?
You may be asking “Who cares if my website takes 5 MiB or 500 MiB to load?” If you have this thought, you are probably a fortunate individual who lives in a place with a fast internet connection. But the truth is a lot of the world doesn’t have an internet connection as fast as yours. Imagine if you had dial-up internet and tried to go to a website with a 2 MiB of JavaScript it could take 5 minutes to load on dial-up. If you live in a rural or developing area this is a reality you may live. A good portion of the internet may not be accessible to you because you would likely timeout before the page ever finished loading. You’re limiting the reach of your content. That could have an impact on your mission.
What Can You Do?
Full disclaimer: I am part of the problem here. I’ve created overly bloated sites that have libraries that probably aren’t needed. It saved time. Sure, but at what cost. I think we developers collectively can do better. That is a big part of the reason that I started this blog. I wanted to show simple solutions to common problems. I only built the hash router I mentioned before because I wanted to write a website without a modern JavaScript framework and see how the experience was. (So far, it is great!) I love NPM. I think it is the best package manager/package registry ever created. But we should be careful with it and use it as sparingly as possible.
My advice is to be careful when pulling in outside dependencies. Ask yourself if you need the library or if it is a problem you can reasonably solve yourself. If you need the library you can pull it in and use it, but you should always ask the question. I would encourage you to evaluate who the target audience is for you and if you can effectively reach them still with your current solution.